package scparser.factory.sceneFactory;

import java.io.BufferedReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import model.Scene;
import model.shader.Shader;
import scparser.ParserHelper;
import scparser.factory.ShaderFactory.ConstantFactory;
import scparser.factory.ShaderFactory.GlassFactory;
import scparser.factory.ShaderFactory.MirrorFactory;
import scparser.factory.ShaderFactory.PhongFactory;
import scparser.factory.ShaderFactory.ShaderAbstractFactory;
import scparser.factory.primitiveFactory.FactoryException;

public class SceneShaderFactory extends SceneFactory {

	public SceneShaderFactory(Scene scene) {
		super.scene = scene;
	}
	
	@Override
	public Object create(BufferedReader br) throws FactoryException {
		List<String> block = new ArrayList<String>();
		String line = null;
		String type = null;
		ShaderAbstractFactory pf = null;
		int brackets = 1;
		
		try {			
			while ((line = br.readLine()) != null) {
				line = line.trim();
				
				if (line.startsWith("type")) {
					type = ParserHelper.takeString(line, "type");
				} else if (line.contains("{")) {
					if (!line.contains("}")) {
						brackets++;
						
					}
				} else if (line.contains("}")) {
					if (brackets == 1) {
						break;
					}
					
					if (brackets == 0) {
						throw new FactoryException("syntax error, check your brackets");
					}
					
					brackets--;
				}
				block.add(line);
			}
		} catch (IOException e) {
			throw new FactoryException(e.getMessage());
		}

		if (type == null) {
			throw new FactoryException("type missing");
		}
		
		if (type.equals("phong")) {
			pf = new PhongFactory(scene);
		}
		
		if (type.equals("mirror")) {
			pf = new MirrorFactory(scene);
		}
		
		if (type.equals("glass")) {
			pf = new GlassFactory(scene);
		}
		
		if (type.equals("constant")) {
			pf = new ConstantFactory(scene);
		}
		
		if (pf == null) {
			throw new FactoryException("shader type not supported");
		}
		
		Shader ret = pf.create(block);
		if (super.scene.getShaders().contains(ret)) {
			throw new FactoryException("shader already exists");
		}
		
		return ret;
	}
	
//	public Object create(BufferedReader br) throws FactoryException {
//		String line = null;
//		String typeString = null;
//		
//		try {
//			while ((line = br.readLine()) != null) {
//				line = line.trim();
//				
////				String[] tokens = line.split(" ");
////				if (tokens[0].contains(Constants.S_CLOSE) && !tokens[0].equals("color")) {
////					break;
////				}
//				
//				if (line.equals(Constants.S_CLOSE)) {
//					break;
//				}
//				
//				if (line.startsWith("type")) {
//					typeString = ParserHelper.takeString(line, "type");
//					
//					//TODO: fixear lo de type
//					this.type = findType(typeString);
//					if (this.type == null) {
//						throw new FactoryException("invalid shader type");
//					}
//				} else if (line.startsWith("diff")) {
//					if (line.contains(Constants.S_OPEN)) {
//						this.diff = getColor(line);
//					} else {
//						this.diff = getColor(br);						
//					}
//					if (diff == null) {
//						throw new FactoryException("in shader object, diff option missing");
//					}
//				} else if (line.startsWith("spec")) {
//					if (line.contains(Constants.S_OPEN)) {
//						this.spec = getSpec(line);
//					} else {
//						this.spec = getSpec(br);						
//					}
//					if (spec == null) {
//						throw new FactoryException("in shader object, spec option missing");
//					}
//				} else if (line.startsWith("color")) {
//					if (line.contains(Constants.S_OPEN)) {
//						this.color = getColor(line);
//					} else {
//						this.color = getColor(br);						
//					}
//					if (color == null) {
//						throw new FactoryException("in shader object, color option missing");
//					}
//				} else if (line.startsWith("name")) {
//					super.name = ParserHelper.takeString(line, "name");
//				}
//			}
//		} catch (IOException e) {
//			throw new FactoryException(e.getMessage());
//		}
//		
//		// TODO: aca vas a tener q poner el factory de shader
//		Shader ret = new Shader(super.name, this.color, this.diff, this.spec, this.type);
//		if (super.scene.getShaders().contains(ret)) {
//			throw new FactoryException("shader already exists");
//		}
//		
//		return ret;
//	}
//
//	//TODO: esto ya va a ser alpedo
//	private Type findType(String typeString) {
//		for (shader.Type t: shader.Type.values()) {
//			if (t.toString().equals(typeString)) {
//				return t;
//			}
//		}
//		return null;
//	}

//	private Spec getSpec(BufferedReader br) throws FactoryException {
//		String line = null;				
//		try {
//			while ((line = br.readLine()) != null) {
//				if (!line.trim().equals("")) {
//					return getSpec(line);
//				}
//			}
//		} catch (IOException e) {
//			throw new FactoryException(e.getMessage());
//		}
//		return null;
//	}
//	
//	private Spec getSpec(String line) throws FactoryException, IOException {
//		Color color;
//		line = line.replaceAll("{", "");
//		line = line.replaceAll("}", "");
//		String[] values = line.split(" ");
//		String type = values[0] + values[1];
//		float r,g,b;
//		
//		if (type == null || type.equals("")) {
//			throw new FactoryException("shader type option missing");
//		}
//		Point3d p;
//		p = ParserHelper.takePoint(line, "\"sRGB nonlinear\"");
//		
//		r = (float) p.x;
//		g = (float) p.y;
//		b = (float) p.z;
//		
//		color = new Color(r,g,b);
//		return new Spec(color, Double.parseDouble(values[values.length-1]));		
//	}
//
//	private PrimitiveColor getColor(BufferedReader br) throws FactoryException{
//		String line = null;				
//		try {
//			while ((line = br.readLine()) != null) {
//				if (!line.trim().equals("")) {
//					return getColor(line);
//				}
//			}
//		} catch (IOException e) {
//			throw new FactoryException(e.getMessage());
//		}
//		
//		return null;
//	}
//	
//	private PrimitiveColor getColor(String line) throws FactoryException, IOException {
//		Color color;
//		line = line.replaceAll("\\{", "");
//		line = line.replaceAll("\\}", "");
//		String[] values = line.trim().split(" ");
//		String type = values [0] + values[1];
//		float r, g, b;	// rgb color
//		
//		if (type == null || type.equals("")) {
//			throw new FactoryException("shader type option missing");
//		}
//		Point3d p;
//		p = ParserHelper.takePoint(line, "\"sRGB nonlinear\"");
//		
//		// obtiene los componentes RGB del color
//		r = (float) p.x;
//		g = (float) p.y;
//		b = (float) p.z;
//		
//		color = new Color(r, g, b);
//		
//		return new PrimitiveColor(color);
//	}

}
